package com.iot08.api.utils.wxpay;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.*;

/**
 * @version 1.0
 * @Description:
 * @time: 2021/2/27 15:36
 * @author: Rock
 */
public class XMLUtil {

    /**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static SortedMap<String, String> xmlToMap(String strXML) throws Exception {
        try {
            SortedMap<String, String> data = new TreeMap<>();
            DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }
            try {
                stream.close();
            } catch (Exception ex) {
                // do nothing
            }
            return data;
        } catch (Exception ex) {
            throw ex;
        }

    }

    /**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key : data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString();
        try {
            writer.close();
        } catch (Exception ex) {
        }
        return output;
    }

    /**
     * @param returnCode
     * @param returnMsg
     * @time: 2021/2/27 18:36
     * @author: Rock
     * @version 1.0
     */
    public static String setXML(String returnCode, String returnMsg) {
        return "<xml><return_code><![CDATA[" + returnCode + "]]></return_code><return_msg><![CDATA[" + returnMsg + "]]></return_msg></xml>";
    }

    /**
     * XML格式字符串转换为Map
     *
     * @param xmlString XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     * */
    public static JSONObject xmlToJSONObject(String xmlString) {
        try {
            Document doc = DocumentHelper.parseText(xmlString);

            Map<String, Object> map = new HashMap();
            Element root = doc.getRootElement();
            for (Iterator<Element> iterator = root.elementIterator(); iterator.hasNext();) {
                Element e = iterator.next();
                List<Element> list = e.elements();
                if (!list.isEmpty()) {
                    map.put(e.getName(), Element2Map(e));
                } else
                    map.put(e.getName(), e.getText());
            }
            return new JSONObject(map);
        }catch (Exception e){
            if(JSONObject.isValidObject(xmlString)){
                return JSONObject.parseObject(xmlString);
            }
            return null;
        }
    }

    public static Map Element2Map(Element e) {
        Map map = new HashMap();
        List list = e.elements();
        if (list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Element iter = (Element) list.get(i);
                List mapList = new ArrayList();

                if (iter.elements().size() > 0) {
                    Map m = Element2Map(iter);
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!obj.getClass().getName()
                                .equals("java.util.ArrayList")) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(m);
                        }
                        if (obj.getClass().getName()
                                .equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(m);
                        }
                        map.put(iter.getName(), mapList);
                    } else
                        map.put(iter.getName(), m);
                } else {
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(iter.getText());
                        }
                        if (obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(iter.getText());
                        }
                        map.put(iter.getName(), mapList);
                    } else
                        map.put(iter.getName(), iter.getText());
                }
            }
        } else
            map.put(e.getName(), e.getText());
        return map;
    }

    public static void main(String[] args) {
        String result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<result  resultCode=\"0\">\n" +
                "    <getDiskResult>\n" +
                "        <parentCatalogID>0Q11diXl808e00019700101000000071</parentCatalogID>\n" +
                "        <nodeCount>1</nodeCount>\n" +
                "        <catalogList  length=\"1\">\n" +
                "            <catalogInfo>\n" +
                "                <catalogName>生词本</catalogName>\n" +
                "                <catalogID>0Q11diXl808e03120231201151215bt2</catalogID>\n" +
                "                <catalogType>0</catalogType>\n" +
                "                <isShared>false</isShared>\n" +
                "                <createTime>20231201151215</createTime>\n" +
                "                <updateTime>20231201151948</updateTime>\n" +
                "                <catalogLevel>4</catalogLevel>\n" +
                "                <shareDoneeCount>0</shareDoneeCount>\n" +
                "                <ETagOprType>1</ETagOprType>\n" +
                "                <openType>0</openType>\n" +
                "                <dirEtag>4194304</dirEtag>\n" +
                "                <tombstoned>0</tombstoned>\n" +
                "                <moved>0</moved>\n" +
                "                <parentCatalogId>0Q11diXl808e03120231129161650n16</parentCatalogId>\n" +
                "                <isFixedDir>0</isFixedDir>\n" +
                "                <path>00019700101000000001/0Q11diXl808e00019700101000000071/0Q11diXl808e03120231129161650n16/0Q11diXl808e03120231201151215bt2</path>\n" +
                "                <owner>13418100840</owner>\n" +
                "                <modifier>13418100840</modifier>\n" +
                "                <shareType>0</shareType>\n" +
                "                <isIngested>1</isIngested>\n" +
                "                <extProp3>\n" +
                "                    <![CDATA[{\"creator\":\"13418100840\"}]]>\n" +
                "                </extProp3>\n" +
                "            </catalogInfo>\n" +
                "        </catalogList>\n" +
                "        <isCompleted>0</isCompleted>\n" +
                "    </getDiskResult>\n" +
                "</result>";

        result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><result resultCode=\"0\"><getDiskResult><parentCatalogID>0Q11diXl808e00019700101000000071</parentCatalogID><nodeCount>1</nodeCount><contentList length=\"1\"><contentInfo><contentID>0Q11diXl808e06920231202110809dbk</contentID><contentName>newWordsNotebook.json</contentName><contentSuffix>json</contentSuffix><contentSize>162</contentSize><contentDesc></contentDesc><isShared>false</isShared><contentType>0</contentType><contentOrigin>2</contentOrigin><updateTime>20231202110809</updateTime><commentCount>0</commentCount><thumbnailURL></thumbnailURL><bigthumbnailURL></bigthumbnailURL><midthumbnailURL></midthumbnailURL><presentURL>http://download.mcloud.139.com:80/storageWeb/servlet/GetFileByURLServlet?root=/mnt/wfs146&amp;fileid=KMd5f09ded9df592b93c2175429be260eb.json&amp;ct=0&amp;type=2&amp;code=E6591D7113C25EE9AA75BFD36502C7965C655B25C50DFFA1FB0E0067CC5C159D&amp;exp=329&amp;account=MFExMWRpWGw4MDhl&amp;p=0&amp;ui=0Q11diXl808e&amp;ci=0Q11diXl808e06920231202110809dbk&amp;userSiteId=usersite-s&amp;cn=newWordsNotebook&amp;oprChannel=10230036&amp;dom=D962</presentURL><presentLURL></presentLURL><presentHURL></presentHURL><shareDoneeCount>0</shareDoneeCount><safestate>0</safestate><transferstate>0</transferstate><isFocusContent>0</isFocusContent><uploadTime>20231202110809</uploadTime><ETagOprType>1</ETagOprType><openType>0</openType><auditResult>0</auditResult><parentCatalogId>0Q11diXl808e03120231129161650n16</parentCatalogId><channel>10214200</channel><digest>CE94BA3A3487C0A3C15B5045D31BA9A8</digest><geoLocFlag>0</geoLocFlag><version></version><fileEtag>1842185668306242577</fileEtag><encryptFlag>0</encryptFlag><fileVersion>1842185668285308898</fileVersion><tombstoned>0</tombstoned><proxyID></proxyID><moved>0</moved><owner>13418100840</owner><modifier>13418100840</modifier><shareType>0</shareType><exif><createTime>19700101000000</createTime></exif><isIngested>1</isIngested><extInfo size=\"1\"><item><key>uploader</key><value>13418100840</value></item></extInfo><extProp3></extProp3></contentInfo></contentList><isCompleted>0</isCompleted></getDiskResult></result>";
        JSONObject resOB = XMLUtil.xmlToJSONObject(result);

        JSONObject getDiskResult = resOB.getJSONObject("getDiskResult");
        JSONObject contentList = getDiskResult.getJSONObject("contentList");
        Object contentInfo = contentList.get("contentInfo");
        if (contentInfo instanceof Map){
            System.out.println("是对象");
        }else if (contentInfo instanceof ArrayList){
            System.out.println("是数组");
        }
        System.out.println(resOB.toJSONString());


        result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "        <result  resultCode=\"0\">\n" +
                "            <String>http://download.mcloud.139.com:80/storageWeb/servlet/downloadServlet?code=S00wUTExZGlYbDgwOGU4MzIxN3UybEdlUElI&amp;un=D0FA91881019A1D1BAF33E50CA8DF2E4A8EE71AE62420D6CE25A9B723D81980E&amp;dom=D962&amp;rate=0&amp;txType=0</String>\n" +
                "        </result>";
        resOB = XMLUtil.xmlToJSONObject(result);

        System.out.println(resOB.toJSONString());


        result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "        <result  resultCode=\"0\">\n" +
                "            <uploadResult>\n" +
                "                <uploadTaskID>KB0Q11diXl808e22417u2lHCkNn</uploadTaskID>\n" +
                "                <redirectionUrl>http://upload.mcloud.139.com:80/storageWeb/servlet/uploadFileServlet?uploadCode=S0IwUTExZGlYbDgwOGUyMjQxN3UybEhDa05u&amp;txType=0&amp;oprChannel=10230036&amp;dom=D961&amp;rate=0</redirectionUrl>\n" +
                "                <newContentIDList  length=\"1\">\n" +
                "                    <newContent>\n" +
                "                        <contentID>0Q11diXl808e06920231202144445jvv</contentID>\n" +
                "                        <contentName>outLineVoice.amr</contentName>\n" +
                "                        <isNeedUpload>1</isNeedUpload>\n" +
                "                        <fileEtag>1842240175971113056</fileEtag>\n" +
                "                        <overridenFlag>0</overridenFlag>\n" +
                "                        <fileVersion>1842240175971113057</fileVersion>\n" +
                "                    </newContent>\n" +
                "                </newContentIDList>\n" +
                "            </uploadResult>\n" +
                "        </result>";
        resOB = XMLUtil.xmlToJSONObject(result);

        System.out.println(resOB.toJSONString());

        result = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<result  resultCode=\"200000501\" desc=\"[501225|F9E37BA46CA04EF3B03917FCA5381B8F]Failed to invoke the service.0[NDA(100590)][Flag:F9E37BA46CA04EF3B03917FCA5381B8F]\">\n" +
                "</result>";
        resOB = XMLUtil.xmlToJSONObject(result);

        System.out.println(resOB.toJSONString());


        result = "<?xml version='1.0' encoding='utf-8'?> <result resultCode=\"20011\" desc=\"accesstoken无效\"> </result>";
        resOB = XMLUtil.xmlToJSONObject(result);

        System.out.println(resOB.toJSONString());

    }
}
